package com.theaf.core.opensearch;


import com.aliyun.opensearch.DocumentClient;
import com.aliyun.opensearch.OpenSearchClient;
import com.aliyun.opensearch.SearcherClient;
import com.aliyun.opensearch.sdk.dependencies.com.google.common.collect.Lists;
import com.aliyun.opensearch.sdk.dependencies.org.json.JSONArray;
import com.aliyun.opensearch.sdk.dependencies.org.json.JSONObject;
import com.aliyun.opensearch.sdk.generated.OpenSearch;
import com.aliyun.opensearch.sdk.generated.commons.OpenSearchClientException;
import com.aliyun.opensearch.sdk.generated.commons.OpenSearchException;
import com.aliyun.opensearch.sdk.generated.commons.OpenSearchResult;
import com.aliyun.opensearch.sdk.generated.document.Command;
import com.aliyun.opensearch.sdk.generated.document.DocumentConstants;
import com.aliyun.opensearch.sdk.generated.search.*;
import com.aliyun.opensearch.sdk.generated.search.general.SearchResult;
import com.aliyun.opensearch.search.SearchParamsBuilder;
import org.springframework.util.CollectionUtils;

import java.util.*;

public class AliSearch {
    private static String accesskey = "LTAIKNbQWFTR9rVg";
    private static String secret = "UXSIWQ4uMbWknJdu8Z0GkhhL2ZXpl9";
    private static String host = "http://opensearch-cn-qingdao.aliyuncs.com";

    private static OpenSearch openSearch;
    private static OpenSearchClient openSearchClient;
    private static SearcherClient searcherClient;

    static{
        //创建并构造OpenSearch对象
        openSearch = new OpenSearch(accesskey, secret, host);
        //创建OpenSearchClient对象，并以OpenSearch对象作为构造参数
        openSearchClient = new OpenSearchClient(openSearch);
        //创建SearcherClient对象，并以OpenSearchClient对象作为构造参数
        searcherClient = new SearcherClient(openSearchClient);
    }

    /**
     * 下拉提示
     *
     * @param appName     搜索的应用
     * @param suggestName 下拉提示名称
     * @param query       设置查询词
     * @param pageNo      页码
     * @param pageSize    每页大小
     * @return
     */
    public static Map suggest(String appName, String suggestName, String query, Integer pageNo, Integer pageSize) {
        //定义Config对象，用于设定config子句参数，分页或数据返回格式，指定应用名等等
        Config config = new Config(Lists.newArrayList(appName));
        config.setStart(pageNo);
        config.setHits(pageSize);
        config.setSearchFormat(SearchFormat.JSON);

        // 创建参数对象
        SearchParams searchParams = new SearchParams(config);

        Suggest sug = new Suggest();
        sug.setSuggestName(suggestName);
        searchParams.setSuggest(sug);//searchParams对象添加下拉对象
        searchParams.setQuery(query);//在控制台中下拉列表中如果能搜出"nihao"，这里也能够搜出

        // SearchParams的工具类，提供了更为便捷的操作
        SearchParamsBuilder paramsBuilder = SearchParamsBuilder.create(searchParams);
        // 执行返回查询结果
        SearchResult searchResult;
        String result = "";
        Map<String, Object> ret = null;
        try {
            searchResult = searcherClient.execute(paramsBuilder);
            result = searchResult.getResult();
            JSONObject obj = new JSONObject(result);
            //判断执行返回是否成功，如果报错执行下面代码，否者输出正确查询内容
            List<String> suggestions = new ArrayList<String>();
            if (!obj.has("errors")) {
                JSONArray itemsJsonArray = (JSONArray) obj.get("suggestions");
                for (int i = 0; i < itemsJsonArray.length(); i++) {
                    JSONObject item = (JSONObject) itemsJsonArray.get(i);
                    suggestions.add(item.getString("suggestion"));
                }
                ret = new HashMap<String, Object>();
                ret.put("result", suggestions);
                ret.put("status", "OK");
                System.out.println(new JSONObject(ret).toString());
            } else {
                ;
            }
        } catch (OpenSearchException e) {
            e.printStackTrace();
        } catch (OpenSearchClientException e) {
            e.printStackTrace();
        }
        return ret;
    }

    /**
     * @param appName     搜索的应用
     * @param queryString 查询子句
     * @param filterMap   过滤条件
     * @param sortMap     排序规则
     * @param fetchFields 搜索结果返回的字段
     * @param summaryList 设置搜索结果摘要信息
     * @param pageNo      页码
     * @param pageSize    每页大小
     * @return
     * @throws Exception
     */
    public static String search(String appName, String queryString, Map<String, String> filterMap, Map<String, Integer> sortMap, List<String> fetchFields, List<Map<String, String>> summaryList, Integer pageNo, Integer pageSize) throws Exception {
        //定义Config对象，用于设定config子句参数，指定应用名，分页，数据返回格式等等
        Config config = new Config(Lists.newArrayList(appName));
        config.setStart(pageNo);
        config.setHits(pageSize);
        //设置返回格式为json格式
        config.setSearchFormat(SearchFormat.JSON);
        if (!CollectionUtils.isEmpty(fetchFields)) {
            // 设置搜索结果返回应用中哪些字段
            config.setFetchFields(fetchFields);
        }
        // 创建参数对象
        SearchParams searchParams = new SearchParams(config);
        // 指定搜索的关键词，这里要指定在哪个索引上搜索，如果不指定的话默认在使用“default”索引（索引字段名称是您在您的数据结构中的“索引字段列表”中对应字段。），若需多个索引组合查询，需要在setQuery处合并，否则若设置多个setQuery子句，则后面的子句会替换前面子句
        searchParams.setQuery(queryString);
        if (!CollectionUtils.isEmpty(sortMap)) {
            //创建sort对象
            Sort sort = new Sort();
            for (Map.Entry<String, Integer> entry : sortMap.entrySet()) {
                String key = entry.getKey();
                Integer value = entry.getValue();
                if (1 == value) // 降序
                {
                    sort.addToSortFields(new SortField(key, Order.DECREASE));
                } else if (2 == value) // 升序
                {
                    sort.addToSortFields(new SortField(key, Order.INCREASE));
                }
            }
            searchParams.setSort(sort);
        }

        if (!CollectionUtils.isEmpty(summaryList)) {
            for (Map<String, String> summaryMap : summaryList) {
                Summary summary = new Summary();
                for (Map.Entry<String, String> entry : summaryMap.entrySet()) {
                    String key = entry.getKey();
                    String value = entry.getValue();
                    if ("field".equals(key)) {
                        summary.setSummary_field(value); //指定的生效的字段。此字段必需为可分词的text类型的字段。
                    } else if ("len".equals(key)) {
                        summary.setSummary_len(value); //片段长度
                    } else if ("em".equals(key)) {
                        summary.setSummary_element(value); //飘红标签
                    } else if ("ellipsis".equals(key)) {
                        summary.setSummary_ellipsis(value); //片段链接符
                    } else if ("snippet".equals(key)) {
                        summary.setSummary_snippet(value); //片段数量
                    }
                }
                searchParams.addToSummaries(summary);
            }
        }

        //执行查询语句返回数据对象
        SearchParamsBuilder paramsBuilder = SearchParamsBuilder.create(searchParams);
        if (!CollectionUtils.isEmpty(filterMap)) {
            for (Map.Entry<String, String> entry : filterMap.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                paramsBuilder.addFilter(key, value);
            }
        }
        SearchResult searchResult = searcherClient.execute(paramsBuilder);
        //以字符串返回查询数据
        String result = searchResult.getResult();
        System.out.println(result);
        JSONObject obj = new JSONObject(result);
        JSONObject jsonObject = obj.getJSONObject("result");
        int total = jsonObject.getInt("total");
        int num = jsonObject.getInt("num");
        int viewtotal = jsonObject.getInt("viewtotal");
        List itemList = new ArrayList();
        JSONArray jsonArray = jsonObject.getJSONArray("items");
        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject temp = (JSONObject) jsonArray.getJSONObject(i);
            //temp = temp.getJSONObject("fields");
            Map item = new HashMap();
            Iterator it = temp.keys();
            while (it.hasNext()) {
                String k = String.valueOf(it.next());
                item.put(k, (String) temp.get(k));
            }
            itemList.add(item);
        }
        Map searchRetMap = new HashMap();
        searchRetMap.put("total", total);
        searchRetMap.put("num", num);
        searchRetMap.put("viewtotal", viewtotal);
        searchRetMap.put("itemList", itemList);
        //System.out.println(searchRetMap);
        return result;
    }

    public static void push(String appName, String tableName, List<Map<String, Object>> list) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        JSONArray docsJsonArr = new JSONArray();
        for (Map<String, Object> map : list) {
            JSONObject json = new JSONObject();
            json.put(DocumentConstants.DOC_KEY_CMD, Command.ADD.toString());
            json.put(DocumentConstants.DOC_KEY_FIELDS, map);
            docsJsonArr.put(json);//新增文档
        }
        String docsJson = docsJsonArr.toString();
        System.out.println(docsJson);
        //定义DocumentClient对象添加json格式doc数据批量提交
        DocumentClient documentClient = new DocumentClient(openSearchClient);
        try {
            //执行推送操作
            OpenSearchResult osr = documentClient.push(docsJson, appName, tableName);
            //判断数据是否推送成功，主要通过判断2处，第一处判断用户方推送是否成功，第二处是应用控制台中有无报错日志
            //用户方推送成功后，也有可能在应用端执行失败，此错误会直接在应用控制台错误日志中生成，比如字段内容转换失败
            if (osr.getResult().equalsIgnoreCase("true")) {
                System.out.println("用户方推送无报错！\n以下为getTraceInfo推送请求Id:" + osr.getTraceInfo().getRequestId());
            } else {
                System.out.println("用户方推送报错！" + osr.getTraceInfo());
            }
        } catch (OpenSearchException e) {
            e.printStackTrace();
        } catch (OpenSearchClientException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        Map<String, Integer> sortMap = new HashMap<String, Integer>();
        sortMap.put("id", 1);
        Map<String, String> filterMap = new HashMap<String, String>();
        filterMap.put("type_id=66", "AND");

        Map<String,String> summaryMap = new HashMap<String,String>();
        summaryMap.put("field","title");
        summaryMap.put("em","em");
        summaryMap.put("len","50");
        summaryMap.put("ellipsis","...");
        summaryMap.put("snippet","1");

        List summaryList = new ArrayList();
        summaryList.add(summaryMap);

        AliSearch.search("test", "default:'搜索'", null, sortMap, null, summaryList,0, 5);

        AliSearch.suggest("test", "suggest", "搜索", 0, 10);

        //Map<String, Object> doc1 = Maps.newLinkedHashMap();
        //doc1.put("id", 10);
        //doc1.put("type_id", 66);
        //String title_string = "新增数据Push方式文档1\\\\搜索";// utf-8
        //String body_string = "6666666测试";
        //String author_string = "7777777测试";
        //String tag_string = "8888888测试";
        //byte[] bytes;
        //try {
        //    bytes = title_string.getBytes("utf-8");
        //    doc1.put("title", new String(bytes, "utf-8"));
        //    bytes = body_string.getBytes("utf-8");
        //    doc1.put("body", new String(bytes, "utf-8"));
        //    bytes = author_string.getBytes("utf-8");
        //    doc1.put("author", new String(bytes, "utf-8"));
        //    bytes = tag_string.getBytes("utf-8");
        //    doc1.put("tag", new String(bytes, "utf-8"));
        //
        //} catch (UnsupportedEncodingException e) {
        //    e.printStackTrace();
        //}
        //doc1.put("url", "3333333");
        //doc1.put("create_timestamp", 30);
        //doc1.put("update_timestamp", 60);
        //doc1.put("topped", 90);
        //doc1.put("special", 321);
        //doc1.put("hits", 345);
        //doc1.put("replies", 123);
        //doc1.put("cat_id", 3456);
        //doc1.put("test",Lists.newArrayList("1","2","3"));
        //
        //List<Map<String,Object>> list = new ArrayList<Map<String, Object>>();
        //list.add(doc1);
        //AliSearch.push("test","main",list);

        //String d_name = "信息部";
        //byte[] bytes = d_name.getBytes("utf-8");
        //
        //Map<String,Object> map = new HashMap<String,Object>();
        //map.put("id",1);
        //map.put("d_name",new String(bytes, "utf-8"));
        //
        //d_name = "配件部";
        //bytes = d_name.getBytes("utf-8");
        //Map<String,Object> map2 = new HashMap<String,Object>();
        //map2.put("id",2);
        //map2.put("d_name",new String(bytes, "utf-8"));
        //
        //d_name = "用品部";
        //bytes = d_name.getBytes("utf-8");
        //Map<String,Object> map3 = new HashMap<String,Object>();
        //map3.put("id",3);
        //map3.put("d_name",new String(bytes, "utf-8"));
        //
        //d_name = "财务部";
        //bytes = d_name.getBytes("utf-8");
        //Map<String,Object> map4= new HashMap<String,Object>();
        //map4.put("id",4);
        //map4.put("d_name",new String(bytes, "utf-8"));
        //
        //List<Map<String,Object>> list = new ArrayList<Map<String, Object>>();
        //list.add(map);
        //list.add(map2);
        //list.add(map3);
        //list.add(map4);
        //AliSearch.push("test1","department",list);


        String ryName = "张三";
        byte[]  bytes = ryName.getBytes("utf-8");
        Map<String,Object> ryMap = new HashMap<String,Object>();
        ryMap.put("id",1);
        ryMap.put("name",new String(bytes, "utf-8"));
        ryMap.put("department_id",1);
        ryMap.put("ids",Lists.newArrayList(1,2,3,4,5,6,7));


        ryName = "李四";
        bytes = ryName.getBytes("utf-8");
        Map<String,Object> ryMap2 = new HashMap<String,Object>();
        ryMap2.put("id",2);
        ryMap2.put("name",new String(bytes, "utf-8"));
        ryMap2.put("department_id",1);
        ryMap2.put("ids",Lists.newArrayList(1,2,3,4,5,6,7));
        ryName = "王五";
        bytes = ryName.getBytes("utf-8");
        Map<String,Object> ryMap3 = new HashMap<String,Object>();
        ryMap3.put("id",3);
        ryMap3.put("name",new String(bytes, "utf-8"));
        ryMap3.put("department_id",2);
        ryMap3.put("ids",Lists.newArrayList(1,2,3,4,5,6,7));

        ryName = "刘彬";
        bytes = ryName.getBytes("utf-8");
        Map<String,Object> ryMap4 = new HashMap<String,Object>();
        ryMap4.put("id",4);
        ryMap4.put("name",new String(bytes, "utf-8"));
        ryMap4.put("department_id",3);
        ryMap4.put("ids",Lists.newArrayList(1,2,3,4,5,6,7));

        ryName = "曾诚";
        bytes = ryName.getBytes("utf-8");
        Map<String,Object> ryMap5 = new HashMap<String,Object>();
        ryMap5.put("id",5);
        ryMap5.put("name",new String(bytes, "utf-8"));
        ryMap5.put("department_id",4);
        ryMap5.put("ids",Lists.newArrayList(1,2,3,4,5,6,7,8));

        List<Map<String,Object>> ryList = new ArrayList<Map<String, Object>>();
        ryList.add(ryMap);
        ryList.add(ryMap2);
        ryList.add(ryMap3);
        ryList.add(ryMap4);
        ryList.add(ryMap5);

        AliSearch.push("test1","personnel",ryList);

    }


}
